package com.thinkit.bigdata.web.service.impl.sec;

import com.thinkit.bigdata.core.feature.orm.mybatis.Page;
import com.thinkit.bigdata.core.util.StringUtil;
import com.thinkit.bigdata.web.dao.config.SysAreaMapper;
import com.thinkit.bigdata.web.dao.sec.SysGroupMapper;
import com.thinkit.bigdata.web.dao.sec.SysUserMapper;
import com.thinkit.bigdata.web.model.config.SysArea;
import com.thinkit.bigdata.web.model.config.SysAreaExample;
import com.thinkit.bigdata.web.model.result.Constants;
import com.thinkit.bigdata.web.model.result.HtmlResult;
import com.thinkit.bigdata.web.model.sec.*;
import com.thinkit.bigdata.web.service.sec.GroupService;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 * Created by lihongli on 2018/9/17
 */
@Service
public class GroupServiceImpl implements GroupService {
    @Resource
    private SysGroupMapper mapper;

    @Resource
    private SysAreaMapper areaMapper;

    @Resource
    private SysUserMapper userMapper;

    @Override
    public SysGroup selectByPrimaryKey(Long id) {
        return mapper.selectByPrimaryKey(id);
    }

    @Override
    public List<SysGroup> selectByExample(SysGroupExample example) {
        return mapper.selectByExample(example);
    }

    @Override
    public List<SysGroup> selectByExample(Page<SysGroup> page, SysGroupExample example) {
        mapper.selectByExample(page, example);
        List<SysGroup> result = page.getResult();
        for (SysGroup group : result) {
            if (group.getParentid() == null) continue;
            // 循环遍历获取A-B-C机构的名称
            StringBuilder sb = new StringBuilder();
            List<Long> tmp = new ArrayList<>();
            tmp.add(group.getParentid());
            while (!tmp.isEmpty()) {
                Long id = tmp.remove(0);
                SysGroupExample example2 = new SysGroupExample();
                example2.createCriteria().andIdEqualTo(id);
                List<SysGroup> groupList = mapper.selectByExample(example2);
                for (SysGroup sysGroup : groupList) {
                    if (sb.length() == 0) sb.insert(0, sysGroup.getName());
                    else sb.insert(0, sysGroup.getName() + "-");
                    if (sysGroup.getParentid() != null) tmp.add(sysGroup.getParentid());
                }
            }
            group.setParentname(sb.toString());
        }
        return result;
    }

    @Override
    public Integer countByExample(SysGroupExample example) {
        return mapper.countByExample(example);
    }

    @Override
    public Integer insert(SysGroup record) {
        return mapper.insertSelective(record);
    }

    @Override
    public SysGroup groupGetByPK(Long id) {
        return mapper.selectByPrimaryKey(id);
    }

    @Override
    public Integer update(SysGroup record) {
        return mapper.updateByPrimaryKeySelective(record);
    }

    @Override
    public Integer groupDeleteBatch(List<Long> idList) {
        // 循环遍历删除
        int rowNum = 0;
        for (Long id : idList) {
            rowNum += delRecursion(id);
        }
        return rowNum;
    }

    @Override
    public Integer statusSingle(SysGroup record, Long id) {
        return statusRecursion(record, id);
    }

    @Override
    public Integer statusBatch(SysGroup record, List<Long> idList) {
        int rowNum = 0;
        for (Long id : idList) {
            rowNum += statusRecursion(record, id);
        }
        return rowNum;
    }

    /**
     * 查询机构树 结构设计
     * 根节点rootNode 中国电信节点 无实际用处
     * 第二级节点 areaNode 省份节点
     * 第三级节点 以及以下节点 groupNode机构节点
     *
     * @param areaId
     * @return
     */
    @Override
    public JsTreeNode getTreeData(Integer areaId) {
        // 初始化树的基础信息
        JsTreeNode rootNode = new JsTreeNode();
        rootNode.setId(-10000L);
        rootNode.setText("中国电信");
        if (areaId == null) {
            // 查询所有省份机构信息
            SysAreaExample areaExample = new SysAreaExample();
            // 设置只查询已开放服务的省份 1启用
            areaExample.createCriteria().andEnabledEqualTo(1);
            areaExample.setOrderByClause("id asc");
            List<SysArea> areaList = areaMapper.selectByExample(areaExample);
            // 构建一个集团节点 因为省份表里没有集团
            JsTreeNode groupNode = new JsTreeNode();
            groupNode.setId(-Constants.GROUP_AREAID);
            groupNode.setText("集团");
            rootNode.getChildren().add(groupNode);
            // 循环添加省份节点
            for (SysArea area : areaList) {
                JsTreeNode areaNode = new JsTreeNode();
                areaNode.setId(-area.getId().longValue());
                areaNode.setText(area.getArea());
                rootNode.getChildren().add(areaNode);
            }
        } else {
            // 查询单个省份机构信息 先构建省份节点 (用户页面有传入集团id-9999额外处理下)
            JsTreeNode areaNode = new JsTreeNode();
            if (areaId.longValue() == Constants.GROUP_AREAID.longValue()) {
                areaNode.setId(-areaId.longValue());
                areaNode.setText("集团");
            } else {
                SysArea area = areaMapper.selectByPrimaryKey(areaId);
                areaNode.setId(-area.getId().longValue());
                areaNode.setText(area.getArea());
            }
            rootNode.getChildren().add(areaNode);
        }
        // 构建机构节点
        List<JsTreeNode> areaNodeList = rootNode.getChildren();
        for (JsTreeNode areaNode : areaNodeList) {
            SysGroupExample example = new SysGroupExample();
            example.createCriteria().andAreaidEqualTo(Math.abs(areaNode.getId()));
            List<SysGroup> groupList = mapper.selectByExample(example);
            buildGroupNode(areaNode, groupList);
        }
        return rootNode;
    }

    /**
     * 新增机构树  结构设计
     * 根节点 就是 省份节点 areaNode
     * 第二级级以下各级节点 均为 机构节点， 查询的时候应该只取出机构类型为运营管理的机构
     *
     * @param areaId
     * @return
     */
    @Override
    public JsTreeNode getAddTreeData(Integer areaId) {
        JsTreeNode areaNode = new JsTreeNode();
        areaNode.setId(-areaId.longValue());
        if (areaId.longValue() != Constants.GROUP_AREAID.longValue()) {
            SysArea area = areaMapper.selectByPrimaryKey(areaId);
            areaNode.setText(area.getArea());
        } else {
            areaNode.setText("集团");
        }
        // 查询出集团或某个省份所有类型为运营管理的机构信息
        SysGroupExample example = new SysGroupExample();
        example.createCriteria().andAreaidEqualTo(Math.abs(areaNode.getId())).andTypeEqualTo(2);
        List<SysGroup> groupList = mapper.selectByExample(example);
        buildGroupNode(areaNode, groupList);
        return areaNode;
    }

    /**
     * 修改机构树  结构设计
     * 根节点 就是 省份节点 areaNode
     * 第二级级以下各级节点 均为 机构节点， 查询的时候应该只取出机构类型为运营管理的机构、且不能查询出原机构下的结构
     *
     * @param areaId
     * @return
     */
    @Override
    public JsTreeNode getEditTreeData(Integer areaId, Long groupId) {
        // 先构建省份节点
        JsTreeNode areaNode = new JsTreeNode();
        areaNode.setId(-areaId.longValue());
        if (areaId.longValue() != Constants.GROUP_AREAID.longValue()) {
            SysArea area = areaMapper.selectByPrimaryKey(areaId);
            areaNode.setText(area.getArea());
        } else {
            areaNode.setText("集团");
        }
        // 获取要展示的机构数据（不包含原机构及其下机构信息、不包含坐席与质检组信息）
        List<Long> idList = new ArrayList<>();
        allSubGroupId(groupId, idList);
        // 排除以上id 查询数据
        SysGroupExample example = new SysGroupExample();
        SysGroupExample.Criteria criteria = example.createCriteria();
        criteria.andAreaidEqualTo(areaId.longValue()).andTypeEqualTo(2).andIdNotIn(idList);
        List<SysGroup> groupList = mapper.selectByExample(example);
        buildGroupNode(areaNode, groupList);
        return areaNode;
    }

    // 循环遍历机构信息 构建父机构id为null的机构节点pNode
    private void buildGroupNode(JsTreeNode areaNode, List<SysGroup> groupList) {
        for (SysGroup group : groupList) {
            // 先把父id为null的查询出来
            if (group.getParentid() == null) {
                JsTreeNode pNode = buildNode(group);
                areaNode.getChildren().add(pNode);
                // 然后递归构建pNode的子节点
                buildSubGroupNode(pNode, groupList);
            }
        }
    }

    // 循环遍历机构信息 构建子节点机构subNode
    private void buildSubGroupNode(JsTreeNode pNode, List<SysGroup> groupList) {
        for (SysGroup group : groupList) {
            // 比较Long类型的数据值是否相等
            if (group.getParentid() != null && group.getParentid().longValue() == pNode.getId().longValue()) {
                JsTreeNode subNode = buildNode(group);
                pNode.getChildren().add(subNode);
                // 然后递归构建subNode的子节点
                buildSubGroupNode(subNode, groupList);
            }
        }
    }

    // 根据传入的机构信息创建一个一个节点并返回node
    private JsTreeNode buildNode(SysGroup group) {
        JsTreeNode node = new JsTreeNode();
        node.setId(group.getId());
        String status = (group.getStatus() == 1) ? "【启用】" : "【停用】";
        node.setText(group.getName() + status);
        return node;
    }

    // 递归删除id对应的组织机构下属所有子组织机构
    private Integer delRecursion(Long id) {
        int rowNum = mapper.deleteByPrimaryKey(id);
        // 删除所有属于该组织机构的用户
        UserExample userExample = new UserExample();
        userExample.createCriteria().andGroupidEqualTo(id);
        userMapper.deleteByExample(userExample);
        // 删除所有组对组关系
        mapper.deleteQcRelation(id);//删除质检组
        mapper.deleteSeatRelation(id);//删除坐席组
        SysGroupExample example = new SysGroupExample();
        example.createCriteria().andParentidEqualTo(id);
        List<SysGroup> groups = mapper.selectByExample(example);
        for (SysGroup group : groups) {
            delRecursion(group.getId());
        }
        return rowNum;
    }

    // 递归修改id对应的组织机构下属所有子组织机构的状态
    private Integer statusRecursion(SysGroup record, Long id) {
        SysGroupExample example = new SysGroupExample();
        example.createCriteria().andIdEqualTo(id);
        int rowNum = mapper.updateByExampleSelective(record, example);

        SysGroupExample example2 = new SysGroupExample();
        example2.createCriteria().andParentidEqualTo(id);
        List<SysGroup> groups = mapper.selectByExample(example2);
        for (SysGroup group : groups) {
            statusRecursion(record, group.getId());
        }
        return rowNum;
    }

    // 递归获取某id下所有子组织机构id，存入idList中
    private void allSubGroupId(Long id, List<Long> idList) {
        SysGroupExample example = new SysGroupExample();
        example.createCriteria().andParentidEqualTo(id);
        List<SysGroup> groupList = mapper.selectByExample(example);
        // 把自身id也给放到集合里排除掉 避免死循环
        idList.add(id);
        // 循环添加子机构id
        for (SysGroup group : groupList) {
            idList.add(group.getId());
            allSubGroupId(group.getId(), idList);
        }
    }

    @Override
    public QcRelationDto selectedSeat(Long qcGroupId) {
        return mapper.selectedSeat(qcGroupId);
    }

    @Override
    public Integer insertQcRelation(QcRelationDto qcRelation) {
        int rowNum = mapper.deleteQcRelation(qcRelation.getQcGroupId());
        if (qcRelation.getSeatGroupIdList().isEmpty()) {
            return rowNum;
        }
        return mapper.insertQcRelation(qcRelation);
    }

    @Override
    public HtmlResult insertGroups(List<SysGroup> groupList) {
        // 标记成功导入的数据量
        int rowNum = 0;
        StringBuilder errorMsg = new StringBuilder();
        for (SysGroup group : groupList) {
            // 先判断要写入的机构名称是否存在 (modify on 01/29不同省份是允许重复的 此处查询条件增加areaId)
            SysGroupExample example = new SysGroupExample();
            example.createCriteria().andNameEqualTo(group.getName()).andAreaidEqualTo(group.getAreaid());
            // 如果已经存在了 则不写入
            if (mapper.countByExample(example) > 0) {
                errorMsg.append("第" + group.getRownum() + "行机构已存在;");
                continue;
            }
            // 上级组织机构名称
            String parentName = group.getParentname();
            if ("".equals(parentName)) {
                // 如果上级组织机构名称为空 直接写入数据库
                rowNum += mapper.insertSelective(group);
            } else {
                // 根据名称获取上级组织机构的id (modify on 01/29不同省份是允许重复的 此处查询条件增加areaId)
                SysGroupExample example2 = new SysGroupExample();
                example2.createCriteria().andNameEqualTo(parentName).andAreaidEqualTo(group.getAreaid());
                List<SysGroup> parentGroup = mapper.selectByExample(example2);
                if (parentGroup.isEmpty() || parentGroup.size() > 1) {
                    // 如果父级机构为0个或多个 则不写入
                    errorMsg.append("第" + group.getRownum() + "行上级组织机构不存在;");
                    continue;
                }
                // 判断上级机构类型是不是部门 如果不是则不允许添加子机构
                if (parentGroup.get(0).getType() != 2) {
                    errorMsg.append("第" + group.getRownum() + "行所属机构下不可再添加机构");
                    continue;
                }
                // 为要写入数据库的组织机构设置父级组织机构
                group.setParentid(parentGroup.get(0).getId());
                rowNum += mapper.insertSelective(group);
            }
        }
        HtmlResult htmlResult = new HtmlResult();
        htmlResult.setCount(rowNum);
        htmlResult.setMsg(errorMsg.toString());
        return htmlResult;
    }

    @Override
    public Long insertGroupsOnBatchImportUser(String groupListName, String groupTypeName, Long areaid, Long loginUserId) {
        // 获取组织机构类型
        Integer groupType = getGroupType(groupTypeName);
        // 校验组织机构 判断是否插入
        String[] groupArray = groupListName.split("-");
        int length = groupArray.length;
        Long parentId = null;
        for (int i = 0; i < length; i++) {
            String groupName = groupArray[i];
            if (StringUtil.isEmpty(groupName)) {
                return Constants.ERROR_GROUP_NAME_EMPTY;
            }
            // 校验机构是否存在
            SysGroupExample example = new SysGroupExample();
            example.createCriteria().andNameEqualTo(groupName).andAreaidEqualTo(areaid);
            List<SysGroup> groupList = mapper.selectByExample(example);
            if (groupList.isEmpty()) {
                // 如果机构不存在 新增
                SysGroup group = new SysGroup();
                group.setAreaid(areaid);
                group.setParentid(parentId);
                group.setName(groupName);
                group.setType(i == length - 1 ? groupType : 2);
                group.setStatus(1);
                group.setCreateuserid(loginUserId);
                group.setCreatetime(new Date());
                mapper.insertSelective(group);
                parentId = group.getId();
            } else {
                // 如果机构存在 要求 （1）非最后一个机构类型必须是其他 （2）最后一个机构机构类型必须与后面单元格设置的相同
                SysGroup group = groupList.get(0);
                if ((i < length - 1 && group.getType() != 2) || (i == length - 1 && group.getType() != groupType)) {
                    return Constants.ERROR_GROUP_TYPE_NOT_MATCH;
                }
                // 机构类型校验通过 则把parentid重新赋值 下一次循环如果需要插入时使用
                parentId = group.getId();
            }
        }
        return parentId;
    }

    // 根据机构类型名称转换为应的type值
    private Integer getGroupType(String groupTypeName) {
        if ("坐席".equals(groupTypeName)) {
            return 0;
        } else if ("质检".equals(groupTypeName)) {
            return 1;
        }
        return 2;
    }

    @Override
    public List<GroupAuthDto> selectUnAuthSeatGroupByGroupId(Long groupId, Long areaId) {
        // 查询出来所有未授权的坐席组
        return mapper.selectUnAuthSeatGroupByGroupId(groupId, areaId);
    }

    @Override
    public List<GroupAuthDto> selectAuthSeatGroupByGroupId(Long groupId) {
        // 查询出来所有授权的坐席组
        return mapper.selectAuthSeatGroupByGroupId(groupId);
    }

    @Override
    public List<SysGroup> selectSeatGroupByQcGroupId(Page<SysGroup> page, Long groupId, Long userId) {
        return mapper.selectSeatGroupByQcGroupId(page, groupId, userId);
    }

    @Override
    public List<SysGroup> selectSeatGroupByQcGroupId(Long groupId, Long userId) {
        return mapper.selectSeatGroupByQcGroupId(groupId, userId);
    }

    @Override
    public SysArea selectAreaInfoByGroupId(Long groupId) {
        return mapper.selectAreaInfoByGroupId(groupId);
    }

    @Override
    public List<GroupAuthDto> receiveUnAuthSeatGroup(Long userId, Long groupId, Long areaId) {
        // 查询出来所有未授权的坐席组
        return mapper.receiveUnAuthSeatGroup(userId, groupId, areaId);
    }

    @Override
    public List<GroupAuthDto> receiveAuthSeatGroup(Long userId, Long groupId) {
        // 查询出来所有已授权的坐席组
        return mapper.receiveAuthSeatGroup(userId, groupId);
    }
}
